package com.coupon.couponbatchsend100w.service.impl;

import com.coupon.couponbatchsend100w.service.CouponService;
import jakarta.annotation.Resource;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
@Service
public class CouponServiceImpl implements CouponService {
//    设置下发优惠券的数量：
    public static final Integer COUPON_NUMBER = 50 * 10000;

    @Resource
    private ThreadPoolTaskExecutor threadPool;

    /**
     * 下发50万条优惠券
     */
    @Override
    public void batchTaskAction() {
//    1.模拟要下发的50条优惠券，上游系统给我们下发优惠券源头：
        List<String> coupons = new ArrayList<>(COUPON_NUMBER); //将要下发的优惠券放进list里
        for (int i = 0; i <= COUPON_NUMBER; i++) {
            coupons.add("优惠券："+i);//记录每一条优惠券的序号，塞进list里
        }

//    2.创建countDownLatch，构造器参数为任务数量,作用是允许一个或多个线程等待其他一组线程完成操作后，再继续执行。
//        这样才能保证不丢包，确认全部数据下发完成了，方便我们统计或者重试：
        CountDownLatch countDownLatch = new CountDownLatch(coupons.size()); //初始化一个计数器值为 coupons.size() 的 CountDownLatch 对象，和线程创建没有直接关联。
//        CountDownLatch 的本质：它是一个同步工具，只负责 “计数等待”，不负责 “创建线程”。
        long startTime = System.currentTimeMillis();
        try {

//    3.将优惠券集合逐条发送进线程池高并发处理：
            for (String coupon : coupons) { //遍历每个coupon，每个coupon有自己的序号
                threadPool.execute(() -> {
//               4.交给线程池处理——下发业务逻辑，可以提成一个方法
                    try {
                        sendCoupon(String.format("【%s】发送成功",coupon)); //调用 sendCoupon 方法，执行实际的 “发送优惠券” 业务逻辑。
                    }finally { //调用 countDownLatch.countDown()，将计数器减 1，标记 “当前这个优惠券的处理任务已完成”。
//                5.发送一个少一个任务，计数器就减少一个
                        countDownLatch.countDown();
                    }
                });
            }
//            6.阻塞当前发送完毕后，方法才能继续向下走
            countDownLatch.await();
        }catch (Exception e){
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("--------任务处理完毕，消耗时间: "+(endTime - startTime) + "毫秒");
    }


//    下发优惠券的方法：
    private static void sendCoupon(String coupon){ //模拟 “优惠券发送成功” 的操作。
// 实际业务中，这个方法可能会包含更复杂的逻辑，比如：调用数据库接口，记录优惠券发放记录,
// 调用第三方服务，推送优惠券到用户账户,验证优惠券的有效性等
        System.out.println(coupon);
    }

    private static void sendMoney(String money){
        System.out.println(money);
    }

    private static void sendyqm(String yqm){
        System.out.println(yqm);
    }




}
